package com.mxbbx.wdn.domain.menu;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.mxbbx.wdn.database.DBUtil;
import com.mxbbx.wdn.exception.MenuException;

/**
 * 权限实体类
 * 
 * @author 
 * 
 */
public class Menu {

	private static final String SELECT_PARENT_MENU = "select * from menu where menuPid=? order by menuId asc";
	private static final String SELECT_SELF_MENU = "select * from menu where menuId=? order by menuId asc";
	private static final String SELECT_ROLE_MENU = "select * from role_menu where roleId=? and menuId=?";
	/**
	 * 权限编号
	 */
	private String menuId;
	/**
	 * 权限上一级编号
	 */
	private String menuPid;
	/**
	 * 上一级菜单对象
	 */
	private Menu parent;

	private int level;// 菜单级数

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public Menu getParent() throws SQLException {
		try {
			if (this.parent == null) {
				this.parent = new Menu(this.menuPid);
			}
		} catch (MenuException e) {
			e.printStackTrace();
		}
		return this.parent;
	}

	/**
	 * 权限名称
	 */
	private String menuName;

	private String url;

	public Menu() {

	}

	/**
	 * 构造菜单节点实例
	 * 
	 * @param menuId
	 * @throws MenuException
	 * @throws SQLException
	 */
	public Menu(String menuId) throws MenuException, SQLException {
		this.menuId = menuId;
		this.menuName = "";
		if (!"0".equals(menuId)) {
			loadDB(menuId);
		}
	}

	public Menu(String menuName, String url) throws MenuException {
		this.menuName = menuName;
		this.url = url;
	}

	/**
	 * 删除菜单
	 * 
	 * @param menuId
	 * @throws SQLException
	 */
	public void delMenu(String menuId) throws SQLException {
		Connection conn = null;
		this.menuId = menuId;
		try {
			conn = DBUtil.getConn();
			// 1：开启手动提交事务
			conn.setAutoCommit(false);
			// 2:删除菜单信息
			deleteFromDB(conn);
			// 3:删除关联角色
			unbindRole(conn);
			// 4：提交事务
			conn.commit();
		} catch (SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			DBUtil.close(conn);
		}
	}

	/**
	 * 新增子菜单
	 * 
	 * @throws MenuException
	 */
	public void addMenu(String menuPid, int plevel) throws SQLException {
		Connection conn = null;
		this.menuPid = menuPid;
		this.level = plevel + 1;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);
			// 生成菜单编号
			this.menuId = createMenuid();
			// 保存到数据库
			saveToDB(conn);
			conn.commit();
		} catch (SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			DBUtil.close(conn);
		}
	}

	/**
	 * 删除菜单信息
	 * 
	 * @param conn
	 * @throws SQLException
	 */
	private void deleteFromDB(Connection conn) throws SQLException {

		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"delete from menu where menuId=?");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.menuId);

			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to delete record from table !", e);
		} finally {
			DBUtil.close(pstmt);
		}

	}

	/**
	 * 修改菜单
	 * 
	 * @param menuName
	 * @param url
	 * @throws SQLException
	 */
	public void editMenu(String menuName, String url) throws SQLException {
		Connection conn = null;
		this.menuName = menuName;
		this.url = url;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);
			editToDB(conn);
			conn.commit();
		} catch (SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			DBUtil.close(conn);
		}
	}

	/**
	 * 解除Menu与Role关联
	 * 
	 * @param conn
	 * @throws SQLException
	 */
	public void unbindRole(Connection conn) throws SQLException {

		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"delete from role_menu where menuId=?");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.menuId);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to unbind to Role !", e);
		} finally {
			DBUtil.close(pstmt);
		}

	}

	private void saveToDB(Connection conn) throws SQLException {

		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"insert into menu(menuId,menuName,menuPid,url,level)");
			sqlBuff.append("values(?,?,?,?,?)");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.menuId);
			pstmt.setString(2, this.menuName);
			pstmt.setString(3, this.menuPid);
			pstmt.setString(4, this.url);
			pstmt.setInt(5, this.level);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw e;
		} finally {
			DBUtil.close(pstmt);
		}
	}

	/**
	 * 
	 * @param conn
	 * @throws SQLException
	 */
	private void editToDB(Connection conn) throws SQLException {

		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"update menu t set t.menuName=?,t.url=? where t.menuId=?");
			pstmt = conn.prepareStatement(sqlBuff.toString());

			pstmt.setString(1, this.menuName);
			pstmt.setString(2, this.url);
			pstmt.setString(3, this.menuId);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to update t_menu !", e);
		} finally {
			DBUtil.close(pstmt);
		}
	}

	public boolean hasRole(String roleId) throws MenuException, SQLException {

		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			pstmt = conn.prepareStatement(SELECT_ROLE_MENU);
			int index = 1;
			pstmt.setString(index++, this.menuId);
			pstmt.setString(index, roleId);
			rs = pstmt.executeQuery();
			return rs.next();
		} catch (SQLException e) {

			throw new MenuException("Failed to query roleId=" + roleId
					+ "   from database!", e);
		} finally {
			DBUtil.close(rs, pstmt, conn);
		}

	}

	/**
	 * 自动生成菜单编号
	 * 
	 * @return
	 * @throws SQLException
	 */
	private String createMenuid() throws SQLException {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String sql = "select max(menuId) from menu where menuPid=?";
		try {
			conn = DBUtil.getConn();
			pstmt = conn.prepareStatement(sql);
			int index = 1;
			pstmt.setString(index, this.menuPid);
			rs = pstmt.executeQuery();
			String maxcode = "";
			if (rs.next()) {
				maxcode = rs.getString(1);
			}
			if (maxcode != null) {
				int beginIndex = maxcode.length() - 2;
				String no = maxcode.substring(beginIndex);
				Integer number = Integer.parseInt(no);
				++number;
				// 浣跨敤0琛ヨ冻浣嶆暟
				no = String.format("%02d", number);
				maxcode = this.menuPid + no;
			} else {
				maxcode = this.menuPid + "01";
			}
			return maxcode;
		} catch (SQLException e) {

			throw new SQLException("创建父节点ID" + this.menuId + "失败!", e);
		} finally {
			DBUtil.close(rs, pstmt, conn);
		}
	}

	/**
	 * 加载菜单编号对应的记录信息
	 * 
	 * @param menuId
	 * @throws MenuException
	 * @throws SQLException
	 */
	private void loadDB(String menuId) throws MenuException, SQLException {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			pstmt = conn.prepareStatement(SELECT_SELF_MENU);
			int index = 1;
			pstmt.setString(index, menuId);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				this.menuId = rs.getString("menuId");
				this.menuName = rs.getString("menuName");
				this.menuPid = rs.getString("menuPid");
				this.url = rs.getString("url");
				this.level = rs.getInt("level");

			}
		} catch (SQLException e) {

			throw new MenuException("Failed to load id" + menuId
					+ " from database!", e);
		} finally {
			DBUtil.close(rs, pstmt, conn);
		}
	}

	/**
	 * 获取子一级菜单集合
	 * 
	 * @return
	 * @throws SQLException
	 */
	public List<Menu> children() throws MenuException, SQLException {
		List<Menu> menuList = new ArrayList<Menu>();
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			pstmt = conn.prepareStatement(SELECT_PARENT_MENU);
			int index = 1;
			pstmt.setString(index, this.menuId);
			rs = pstmt.executeQuery();

			while (rs.next()) {
				Menu menu = new Menu();
				menu.setMenuId(rs.getString("menuId"));
				menu.setMenuPid(rs.getString("menuPid"));
				menu.setMenuName(rs.getString("menuName"));
				menu.setUrl(rs.getString("url"));
				menu.setLevel(rs.getInt("level"));
				menuList.add(menu);

			}

		} catch (SQLException e) {

			throw new MenuException("查找下一级菜单集合失败", e);
		} finally {
			DBUtil.close(rs, pstmt, conn);
		}

		return menuList;
	}

	public String getMenuiId() {
		return menuId;
	}

	public void setMenuId(String menuId) {
		this.menuId = menuId;
	}

	public String getMenuPid() {
		return menuPid;
	}

	public void setMenuPid(String menuPid) {
		this.menuPid = menuPid;
	}

	public String getMenuName() {
		return menuName;
	}

	public void setMenuName(String menuName) {
		this.menuName = menuName;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getMenuId() {
		return menuId;
	}

	public void setParent(Menu parent) {
		this.parent = parent;
	}

	public void setLevel(Integer level) {
		this.level = level;
	}

}
